package compositionslist;

import info.clearthought.layout.TableLayout;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CompositionsFrame extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    new CompositionsFrame();
                } catch (IOException e) {
                    System.err.println("Failed to read a file");
                    e.printStackTrace();
                }
            }
        });
    }

    private DefaultListModel listModel;

    private CompositionsFrame() throws IOException {
        initializeComponents();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        Map<String, List<String>> user2compositions = loadCompositions();
        List<ScoredComposition> compositions = evaluateCompositions(user2compositions);

        //print to console
        for (ScoredComposition scoredComposition : compositions)
            System.out.println(scoredComposition);

        for (ScoredComposition composition : compositions)
            listModel.addElement(composition);

        pack();
        setVisible(true);
    }

    private void initializeComponents() {
        TableLayout layout = new TableLayout(new double[]{
                100, TableLayout.FILL, 100
        }, new double[]{
                100, TableLayout.FILL, 8, TableLayout.PREFERRED, 100
        });

        setLayout(layout);

        final JList compositionsList = new JList();
        add(new JScrollPane(compositionsList), "1 1");
        listModel = new DefaultListModel();
        compositionsList.setModel(listModel);
        compositionsList.setCellRenderer(new CompositionsCellRenderer());

        compositionsList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Object selectedValue = compositionsList.getSelectedValue();
                if (e.getClickCount() == 2 && selectedValue != null) {
                    updateScores((ScoredComposition) selectedValue, compositionsList);
                }
            }
        });

        JButton button = new JButton("Сохранить");
        add(button, "1 3");

        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    saveToFile();
                } catch (FileNotFoundException e1) {
                    System.err.println("Failed to save to file");
                    e1.printStackTrace();
                }
            }
        });
    }

    private void updateScores(ScoredComposition oldScoredComposition, JList compositionsList) {
        ScoredComposition newScoredComposition = new ScoredComposition(
                oldScoredComposition.getComposition(),
                oldScoredComposition.getScores() + 1
        );

        int selectedIndex = compositionsList.getSelectedIndex();

        listModel.remove(selectedIndex);
        listModel.add(selectedIndex, newScoredComposition);
    }

    private Map<String, List<String>> loadCompositions() throws IOException {
        //list all files
        File[] files = new File("compositionslist").listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".txt");
            }
        });

        //map users to lists of their compositions
        Map<String, List<String>> user2compositions = new HashMap<String, List<String>>();

        //fill the map
        for (File file : files) {
            String name = file.getName();
            //remove extension
            name = name.substring(0, name.length() - ".txt".length());

            List<String> compositions = new ArrayList<String>();
            user2compositions.put(name, compositions);

            //now read compositions from file
            BufferedReader reader = new BufferedReader(new FileReader(file));
            while (true) {
                String line = reader.readLine();
                if (line == null)
                    break;
                compositions.add(line);
            }
            reader.close();
        }

        return user2compositions;
    }

    private List<ScoredComposition> evaluateCompositions(Map<String, List<String>> user2compositions) {
        //first count all compositions. Map composition to counts
        Map<String, Integer> composition2count = new HashMap<String, Integer>();

        for (String user : user2compositions.keySet()) {
            List<String> compositions = user2compositions.get(user);

            for (String composition : compositions)
                if (composition2count.containsKey(composition))
                    composition2count.put(composition, composition2count.get(composition) + 1);
                else
                    composition2count.put(composition, 1);
        }

        //now convert it to list of scored compositions
        List<ScoredComposition> scoredCompositions = new ArrayList<ScoredComposition>();
        for (String composition : composition2count.keySet()) {
            scoredCompositions.add(new ScoredComposition(
                    composition,
                    composition2count.get(composition)
            ));
        }

        return scoredCompositions;
    }

    private void saveToFile() throws FileNotFoundException {
        PrintStream out = new PrintStream("compositionslist/output.log"); //not txt

        for (int i = 0; i < listModel.getSize(); i++)
            out.println(listModel.getElementAt(i));

        out.close();
    }

}
